﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using UtilZ.Dotnet.Ex.DataStruct;
using UtilZ.Dotnet.Ex.Log;
using UtilZ.Dotnet.Ex.Model;
using UtilZ.Dotnet.WindowsDesktopEx.Winform;

namespace WinFormApp
{
    public partial class FTestObjectPool : Form
    {
        public FTestObjectPool()
        {
            InitializeComponent();
        }

        private LogControl logControl = new LogControl();
        private void FSemaphoreSlim_Load(object sender, EventArgs e)
        {
            logControl.Dock = DockStyle.Fill;
            panelLog.Controls.Add(logControl);

            checkBoxLockLog.Checked = logControl.IsLock;
            checkBoxLockLog.CheckedChanged += CheckBoxLockLog_CheckedChanged;

            var appender = Loger.GetAppenderByName(null, "RedirectAppender") as RedirectAppender;
            if (appender == null)
            {
                appender = new RedirectAppender(new RedirectAppendConfig());
                Loger.GetLoger(null).AddAppender(appender);
            }
            appender.RedirectOuput += Appender_RedirectOuput;
        }

        private void Appender_RedirectOuput(object sender, RedirectOuputArgs e)
        {
            logControl.AddLog($"{e.Item.Message}", e.Item.Level);
        }

        private void CheckBoxLockLog_CheckedChanged(object sender, EventArgs e)
        {
            logControl.IsLock = checkBoxLockLog.Checked;
        }

        private void btnClearLog_Click(object sender, EventArgs e)
        {
            logControl.Clear();
        }



        private SemaphoreSlim _semaphoreSlim = new SemaphoreSlim(3, 3);
        private void btnInit_Click(object sender, EventArgs e)
        {
            //_semaphoreSlim = new SemaphoreSlim(3, 3);
            //Loger.Info($"initialCount:3 maxCount:3");

            _semaphoreSlim = new SemaphoreSlim(3);
            Loger.Info($"initialCount:3");
        }

        private void btnGet_Click(object sender, EventArgs e)
        {
            Task.Factory.StartNew(() =>
            {
                Loger.Info($"{Thread.CurrentThread.ManagedThreadId} get");
                _semaphoreSlim.Wait();
                Loger.Info($"{Thread.CurrentThread.ManagedThreadId} get ok");
            });
        }

        private void btnRelease_Click(object sender, EventArgs e)
        {
            _semaphoreSlim.Release();
            Loger.Info("Release");
        }





        private SingleTypeObjectPool<NameValue<int>> _pool = new SingleTypeObjectPool<NameValue<int>>();
        private int _index = 1;
        private Queue<NameValue<int>> _useQueue = new Queue<NameValue<int>>();

        private void btnInitPool_Click(object sender, EventArgs e)
        {
            _pool.Add(new NameValue<int>(this._index.ToString(), _index));
            Loger.Info($"Add {_index}");
            _index++;
        }



        private void btnTake_Click(object sender, EventArgs e)
        {
            Task.Factory.StartNew(() =>
            {
                Loger.Info($"{Thread.CurrentThread.ManagedThreadId} PoolGet");
                var item = this._pool.Take();
                Loger.Info($"{Thread.CurrentThread.ManagedThreadId} PoolGet {item.Name}");
                this._useQueue.Enqueue(item);
            });
        }

        private void btnTryTake_Click(object sender, EventArgs e)
        {
            Task.Factory.StartNew(() =>
            {
                Loger.Info($"{Thread.CurrentThread.ManagedThreadId} PoolGet");
                if (this._pool.TryTake(10000, out var item))
                {
                    Loger.Info($"{Thread.CurrentThread.ManagedThreadId} PoolGet {item.Name}");
                    this._useQueue.Enqueue(item);
                }
                else
                {
                    Loger.Info($"{Thread.CurrentThread.ManagedThreadId} PoolGet fail");
                }
            });
        }

        private void btnPoolRepleaes_Click(object sender, EventArgs e)
        {
            if (this._useQueue.TryDequeue(out var item))
            {
                this._pool.Add(item);
                Loger.Info($"_pool.Add  {item.Name}");
            }
        }

      
    }
}
